﻿using UnityEngine;
using System.Collections;

[AddComponentMenu("TagMachine/Gameplay/Safe Area")]
public class SafeArea : MonoBehaviour
{
	public string FugitiveTag 		= "Fugitive";
	public string WolfTag 			= "Wolf";

	public float ActivationTime		= 3.0f;
	public float ExpulsionTime		= 10.0f;
	public float ExpulsionForce		= 3.0f;
	public float Transparency 		= 0.4f;
	
	private float m_CurrentActivationTime = 0.0f;
	private float m_CurrentExpulsionTime = 10.0f;
	private Fugitive m_Owner 		= null;
	private Color m_OwnerColor		= Color.white;

	private Color BASE_COLOR		= Color.white;

	void Awake()
	{
		BASE_COLOR.a 				= Transparency;
	}

	// Use this for initialization
	public void Reset() 
	{
		renderer.material.color 	= new Color( 0.0f, 0.0f, 0.0f, 0.4f );
		m_CurrentActivationTime 	= 0.0f;
		m_CurrentExpulsionTime		= ExpulsionForce;
	}

	// Update is called once per frame
	void UpdateColor( Color _Color, float _Ratio ) 
	{
		Color OldColor = new Color(_Color.r * _Ratio,
		                           _Color.g * _Ratio,
		                           _Color.b * _Ratio,
		                           _Color.a);
		
		renderer.material.color = OldColor;
	}

	void Update () 
	{
		if ( m_CurrentActivationTime < ActivationTime ) 
		{
			m_CurrentActivationTime += Time.deltaTime;
			
			UpdateColor( BASE_COLOR, m_CurrentActivationTime / ActivationTime );
		} 
		else if ( m_Owner != null ) 
		{
			m_CurrentExpulsionTime -= Time.deltaTime;
			UpdateColor( m_OwnerColor, m_CurrentExpulsionTime / ExpulsionTime );

			if ( m_CurrentExpulsionTime <= 0.0f ) 
			{
				ExpulseOwner();
			}
		}
	}

	void OnTriggerStay( Collider _Other ) 
	{
		bool NeedCollision = _Other.CompareTag( WolfTag );

		if ( _Other.CompareTag( FugitiveTag ) )
		{
			Fugitive FEComp 	= _Other.GetComponent< Fugitive > ();
			bool IsActivating 	= m_CurrentActivationTime <= ActivationTime;

			// The area is not inactive
			if ( !IsActivating && 
				FEComp != null &&
				// We are the owner or there is none
				(m_Owner == null || FEComp == m_Owner) ) 
			{
				if ( m_Owner == null ) 
				{
					NewOwner( FEComp, new Color( FEComp.BaseColor.r, FEComp.BaseColor.g, FEComp.BaseColor.b, Transparency ) ); 
				}
			}
			else
			{
				NeedCollision = true;
			}
		}
		
		if ( NeedCollision )
		{
			MovingEntity MovingComp 		= _Other.transform.parent.GetComponent< MovingEntity > ();

			Vector3 CollisionVec 			= _Other.transform.position - transform.position;
			CollisionVec.y 					= 0.0f;
			CapsuleCollider OtherCollider 	= _Other as CapsuleCollider;

			// Get penetration on X/Z
			float XPenetration 	= collider.bounds.extents.x - ( Mathf.Abs( CollisionVec.x ) - OtherCollider.radius );
			float ZPenetration 	= collider.bounds.extents.z - ( Mathf.Abs( CollisionVec.z ) - OtherCollider.radius );

			if ( XPenetration < ZPenetration )
			{
				if ( XPenetration > 0.0f )
				{
					CollisionVec.z = 0.0f;
					MovingComp.NavAgent.Move( CollisionVec.normalized * XPenetration );
				}
			}
			else if ( ZPenetration > 0.0f )
			{
				CollisionVec.x = 0.0f;
				MovingComp.NavAgent.Move( CollisionVec.normalized * ZPenetration );
			}
		}
	}
	
	void OnTriggerExit( Collider _Other ) 
	{
		Fugitive FEComp = _Other.GetComponent< Fugitive > ();
		if ( FEComp != null && m_Owner == FEComp ) 
		{
			OwnerLeave();
		}
	}

	void NewOwner( Fugitive _Owner, Color _Color ) 
	{
		m_Owner 				= _Owner;
		m_Owner.IsSafe 			= true;
		m_OwnerColor			= _Color;

		m_CurrentExpulsionTime	= ExpulsionTime;

		renderer.material.color = _Color;
	}

	void OwnerLeave() 
	{
		m_Owner.IsSafe 			= false;
		m_Owner 				= null;
		m_OwnerColor 			= BASE_COLOR;
		renderer.material.color = BASE_COLOR;
	}

	void ExpulseOwner() 
	{
		Vector3 Expulsion 	= Random.insideUnitSphere;
		Expulsion.y 		= 0.0f;
		Expulsion.Normalize();
		Expulsion 			*= ExpulsionForce;

		m_Owner.SafeAreaExpulsed( Expulsion );

		m_CurrentActivationTime = 0.0f;
	}
}
